 /* 
 * Copyright 2013 Dominik Korittki, Steffen Gruschka

   Licensed under the Apache License, Version 2.0 (the "License");
   you may not use this file except in compliance with the License.
   You may obtain a copy of the License at

       http://www.apache.org/licenses/LICENSE-2.0

   Unless required by applicable law or agreed to in writing, software
   distributed under the License is distributed on an "AS IS" BASIS,
   WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
   See the License for the specific language governing permissions and
   limitations under the License.
*/
package beans;

import ejb.EJBManager;
import entity.Mitarbeiter;
import entity.Raum;
import java.util.ArrayList;
import java.util.List;
import javax.ejb.EJB;
import javax.ejb.EJBException;
import javax.faces.application.FacesMessage;
import javax.faces.bean.ManagedBean;
import javax.faces.bean.SessionScoped;
import javax.faces.context.ExternalContext;
import javax.faces.context.FacesContext;
import javax.faces.model.SelectItem;
import javax.transaction.RollbackException;
import javax.transaction.SystemException;

/**
 * Bean für die Raumverwaltungsseiten.
 * Diese Klasse ist neben der MitarbeiterverwaltungsBean hautsächlich für die Logik 
 * des Systems verantwortlich.
 * @author Dominik K
 * @author Steffen G
 */
@ManagedBean(name = "raeumeverwaltung")
@SessionScoped
public class RaeumeVerwaltungBean {
    /**
     * Pfad zur Raum-hinzufügen Seite
     */
    private final static String RAUMHINZUFUEGEN = "./raumanlegen.xhtml?faces-redirect=true";
    /**
     * Pfad zur Raum-bearbeiten Seite
     */
    private final static String RAUMBEARBEITEN = "./raumbearbeiten.xhtml?faces-redirect=true";
    /**
     * Pfad zur Räumeverwaltungs Seite
     */
    private final static String RAEUMEVERWALTUNG = "./raeumeverwaltung.xhtml?faces-redirect=true";
    /**
     * Pfad zur zentralen Verwaltung
     */
    private final static String VERWALTUNG = "../index.xhtml?faces-redirect=true";
    /**
     * EJB für JPA Logik
     */
    @EJB
    private EJBManager ejbm;
    /**
     * Parameter für das Paging von Tabellen
     */
    private int first;
    /**
     * Raum Objekt, welches die Seiten zur Datenspeicherung benutzen
     */
    private Raum raum = new Raum();
    /**
     * Alle Mitarbeiter, die als Checkboxen zum Eintragen zur Auswahl stehen
     */
    private List<SelectItem> befugteCheckboxen = new ArrayList<SelectItem>();
    /**
     * IDs der Mitarbeiter, die in den Checkboxen ausgewählt wurden
     */
    private List<String> selectedItems = new ArrayList<String>();

    /**
     * Erzeugt eine neue Instanz
     */
    public RaeumeVerwaltungBean() {
    }
    
    /**
     * Liefert das first Objekt
     * @return das Objekt
     */
    public int getFirst() {
        return this.first;
    }

    /**
     * Setzt ein neues First Objekt
     * @param first neues Objekt
     */
    public void setFirst(int first) {
        this.first = first;
    }

    /**
     * Liefert das raum Objekt
     * @return das Objekt
     */
    public Raum getRaum() {
        return raum;
    }

    /**
     * Setzt ein neues Raum Objekt
     * @param raum Neues Objekt
     */
    public void setRaum(Raum raum) {
        this.raum = raum;
    }

    /**
     * Liefert das befugteCheckboxen Objekt
     * @return das Objekt
     */
    public List<SelectItem> getBefugteCheckboxen() {
        return befugteCheckboxen;
    }

    /**
     * Setzt ein neues befugteCheckboxen Objekt
     * @param befugteCheckboxen Das Objekt
     */
    public void setBefugteCheckboxen(List<SelectItem> befugteCheckboxen) {
        this.befugteCheckboxen = befugteCheckboxen;
    }

    /**
     * Liefert das selectedItems Objekt
     * @return Das Objekt
     */
    public List<String> getSelectedItems() {
        return selectedItems;
    }

    /**
     * Setzt ein neues selectedItems Objekt
     * @param selectedItems Neues Objekt
     */
    public void setSelectedItems(List<String> selectedItems) {
        this.selectedItems = selectedItems;
    }
    
    /**
     * Liest alle Räume aus der Datenbank und gibt diese als Liste zurück
     * @return Liste aller Mitarbeiter
     */
    public List<Raum> getRaumListe() {
        try {
            return ejbm.getRaeume();
        } catch(EJBException e) {
            exceptionHandler(e);
            return null;
        }
    }

    /**
     * Kann von Commandbuttons oder Links als Weiterleitungsadresse benutzt werden
     * @return Pfad zur Raum-anlegen Seite
     */
    public String zuRaumHinzufuegen() {
        return RAUMHINZUFUEGEN;
    }

    /**
     * Kann von Commandbuttons oder Links als Weiterleitungsadresse benutzt werden.
     * Die bereits ausgewählten Mitarbeiter werden wieder vorselektiert
     * @param r zu bearbeitender Raum
     * @return Pfad zur Raum-bearbeiten Seite
     */
    public String zuRaumBearbeiten(Raum r) {
        raum = r;
        selectedItems.clear();
        befugteCheckboxen.clear();
        for (Mitarbeiter m : ejbm.getMitarbeiter()) {
            SelectItem sItem = new SelectItem(m.getKennkartenNr(),
                    (m.getKennkartenNr() + ": " + m.getVorname() + " " + m.getNachname()));
            if (m.getRaeume().contains(raum)) {
                selectedItems.add(m.getKennkartenNr().toString()); //Vorselektion
            }
            getBefugteCheckboxen().add(sItem);
        }
        return RAUMBEARBEITEN;
    }

    /**
     * Kann von Commandbuttons oder Links als Weiterleitungsadresse benutzt werden
     * @return Pfad zur Räume-verwaltung Seite
     */
    public String zuRaeumeVerwaltung() {
        return RAEUMEVERWALTUNG;
    }

    /**
     * Kann von Commandbuttons oder Links als Weiterleitungsadresse benutzt werden
     * @return Pfad zur Verwaltungs Seite
     */
    public String zuVerwaltung() {
        return VERWALTUNG;
    }

    /**
     * Persistiert einen Raum sowie die Beziehungen zu Mitarbeitern / Befugten
     * @return Pfad zur Verwaltungsseite oder null, 
     * falls eine Fehlernachricht angezeigt werden soll
     */
    public String raumHinzufuegen() {
        try {
            //Eintraege parsen
            //raum.setGebauede(Parser.keineUmlaute(raum.getGebauede()));
            //raum.setName(Parser.keineUmlaute(raum.getName()));
            //Zuerst den Raum einmal persistieren (verhindert Mehrfachpersitierung)
            ejbm.persist(raum);

            //Alle ausgewählten Befugte(Mitarbeiter) als neue Beziehung hinzufügen
            for (String s : selectedItems) {
                Mitarbeiter m = ejbm.findeMitarbeiter(new Long(s));
                raum.befugtenHinzufuegen(m);
                m.raumHinzufuegen(raum);
                ejbm.merge(m); //muss gemacht werden
            }
            ejbm.merge(raum); //nochmal den raum mit neuen beziehungen mergen

            raum = new Raum();
            selectedItems.clear();
            befugteCheckboxen.clear();
            return RAEUMEVERWALTUNG;
        } catch (EJBException e) {
            exceptionHandler(e);
            return null;
        }
    }

    /**
     * Aktualisiert die Informationen eines Raumes.
     * @return Pfad zur Bearbeiten Seite oder null, 
     * falls eine Fehlernachricht angezeigt werden soll
     */
    public String raumBearbeiten() {
        //Zunächst alle Beziehungen von dem Raum zu seinen Befugten löschen
        raum.alleBefugtenEntfernen();
        try {
            for (Mitarbeiter m : ejbm.getMitarbeiter()) {
                m.raumEntfernen(raum);
                ejbm.merge(m);
            }

            //Alle ausgewählten Befugte jetzt wieder als neue Beziehung hinzufügen
            for (String s : selectedItems) {
                Mitarbeiter m = ejbm.findeMitarbeiter(new Long(s));
                raum.befugtenHinzufuegen(m);
                m.raumHinzufuegen(raum);
                ejbm.merge(m);
            }

            //Datenbankpersistierung
            ejbm.merge(raum);
            
            raum = new Raum();
            selectedItems.clear();
            befugteCheckboxen.clear();
            return RAEUMEVERWALTUNG;
        } catch (EJBException e) {
            exceptionHandler(e);
            return null;
        }
    }

    /**
     * Löscht einen Raum aus der DB
     * @param r Zu löschender Raum
     * @return Pfad zur Räumeverwaltung oder null,
     * falls eine Fehlernachricht angezeigt werden muss
     */
    public String raumLoeschen(Raum r) {
        try {
            ejbm.remove(r);
            return RAEUMEVERWALTUNG;
        } catch (EJBException e) {
            exceptionHandler(e);
            return null;
        }
    }

    /**
     * Setzt alle Attribute des gemerkten Raumobjekts zurück, sowie Checkboxinformationen
     * sodass keine alten Informationen in den Formularen angezeigt werden
     */
    public void attributeZuruecksetzen() {
        raum = new Raum();
        selectedItems.clear();
        befugteCheckboxen.clear();
        for (Mitarbeiter m : ejbm.getMitarbeiter()) {
            SelectItem sItem = new SelectItem(m.getKennkartenNr(),
                    (m.getKennkartenNr() + ": " + m.getVorname() + " " + m.getNachname()));
            befugteCheckboxen.add(sItem);
        }
    }
    
    /**
     * Terminiert die Session des zurzeit eingelogten Benutzers
     * @param nutzer Aktuell eingeloggter Nutzer
     * @return Link zur Verwaltungsstartseite, sichtbar ist aufgrund der
     * terminierten Session allerdings die Loginseite
     */
    public String logout(SessionNutzer nutzer) {
        SessionNutzer.logout(nutzer);
        return VERWALTUNG;
    }

    /**
     * Paging Funktion zum Weiterblättern
     */
    public void weiter() {
        first = first + 10;
        if (first == ejbm.getRaeume().size()) {
            first = ejbm.getRaeume().size() - 10;
        }
    }

    /**
     * Paging Funktion zum Zurückblättern
     */
    public void zurueck() {
        first = first - 10;
        if (first <= 0) {
            first = 0;
        }
    }

    /**
     * Paging-Funktion um zu entscheiden ob der zurück-Link angezeigt werden soll
     * @return Link anzeigen oder nicht
     */
    public boolean zurueckVisible() {
        if (first >= 10) {
            return true;
        } else {
            return false;
        }
    }

    /**
     * Paging-Funktion um zu entscheiden ob der weiter-Link angezeigt werden soll
     * @return Link anzeigen oder nicht
     */
    public boolean weiterVisible() {
        if (ejbm.getRaeume().size() > first+10) {
            return true;
            

        } else {
            return false;
        }
    }

    /**
     * Paging-Funktion, die die Anzahl der Seiten anzeigt
     * @return Anzahl der Seiten
     */
    public String pageCounter() {
        return Integer.toString(first / 10 + 1);
    }
    
    /**
     * Gibt an ob Räume vorhanden sind
     * @return true falls es Räume gibt, false falls nein
     */
    public boolean raeumeVorhanden(){
        return getRaumListe().isEmpty();
    }
    
    /**
     * Analysiert die EJBException und generiert Fehlernachrichten für die JSF-Seiten
     * @param e EJBException, welche von der EJB geschmissen wurde
     */
    private void exceptionHandler(EJBException e) {
        if(e.getCausedByException() instanceof SystemException) {
            FacesContext facesContext = FacesContext.getCurrentInstance();
            FacesMessage facesMessage = new FacesMessage(FacesMessage.SEVERITY_ERROR,
                    "Die Datenbank ist nicht erreichbar",
                    "Konnte keine Verbindung mit der Datenbank aufbauen");
            facesContext.addMessage(null, facesMessage);
        } else if(e.getCausedByException() instanceof RollbackException) {
            FacesContext facesContext = FacesContext.getCurrentInstance();
            FacesMessage facesMessage = new FacesMessage(FacesMessage.SEVERITY_ERROR,
                    "Name bereits vorhanden, bitte Anderen wählen",
                    "Es gibt bereits einen Eintrag mit diesem Namen");
            facesContext.addMessage(null, facesMessage);
        } else if(e.getCausedByException() instanceof IllegalArgumentException) {
            FacesContext facesContext = FacesContext.getCurrentInstance();
            FacesMessage facesMessage = new FacesMessage(FacesMessage.SEVERITY_ERROR,
                    "Datenbankeintrag nicht vorhanden",
                    "Konnte den benötigten DB-Eintrag nicht finden");
            facesContext.addMessage(null, facesMessage);
        } else {
            FacesContext facesContext = FacesContext.getCurrentInstance();
            FacesMessage facesMessage = new FacesMessage(FacesMessage.SEVERITY_ERROR,
                    "Es ist ein unbekannter Fehler aufgetreten",
                    "Unbekannter Fehler aufgetreten: " + e.getMessage());
            facesContext.addMessage(null, facesMessage);
        }
    }
}
